package com.yang.oauth2.boot.model;

import cn.hutool.core.collection.CollectionUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;
import org.yang.common.core.enums.UserStatusEnum;
import org.yang.common.core.model.UserInfo;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author: Islands
 * @create: 2024-04-11 20:51
 */

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MyUserDetails implements UserDetails, CredentialsContainer {

    /**
     * 用户ID
     */
    private Long userId;
    /**
     * 用户名
     */
    private String username;
    /**
     * 昵称
     */
    private String nickname;
    /**
     * 头像
     */
    private String avatar;
    /**
     * 密码
     */
    @JsonIgnore
    private String password;
    /**
     * 企业ID
     */
    private Long companyId;
    /**
     * 状态
     */
    private Integer enabled;

    /**
     * 角色
     */
    private List<String> roles;

    /**
     * 权限
     */
    private Collection<GrantedAuthority> authorities;

    private boolean accountNonExpired;

    private boolean accountNonLocked;

    private boolean credentialsNonExpired;

    public MyUserDetails(UserInfo info) {
        this.setUserId(info.getUserId());
        this.setUsername(info.getUsername());
        this.setNickname(info.getNickname());
        this.setPassword(info.getPassword());
        this.setAvatar(info.getAvatar());
        this.setCompanyId(info.getCompanyId());
        this.setEnabled(info.getEnabled().getValue());
        if (CollectionUtil.isNotEmpty(info.getPerms())) {
            authorities = info.getPerms().stream()
                    .map(SimpleGrantedAuthority::new)
                    .collect(Collectors.toSet());
        }
        if (CollectionUtil.isNotEmpty(info.getRoles())) {
            this.setRoles(info.getRoles());
        }
    }


    public MyUserDetails(
            Long userId,
            String username,
            String nickname,
            String password,
            Long companyId,
            Integer enabled,
            boolean accountNonExpired,
            boolean credentialsNonExpired,
            boolean accountNonLocked,
            Set<? extends GrantedAuthority> authorities
    ) {
        this.userId = userId;
        this.username = username;
        this.nickname = nickname;
        this.password = password;
        this.companyId = companyId;
        this.enabled = enabled;
        this.accountNonExpired = accountNonExpired;
        this.credentialsNonExpired = credentialsNonExpired;
        this.accountNonLocked = accountNonLocked;
        this.authorities = Collections.unmodifiableSet(authorities);
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    /**
     * 过期
     */
    @Override
    public boolean isAccountNonExpired() {
        return !this.enabled.equals(UserStatusEnum.OVERDUE.getValue());
    }

    /**
     * 锁定
     */
    @Override
    public boolean isAccountNonLocked() {
        return !this.enabled.equals(UserStatusEnum.LOCK.getValue());
    }

    /**
     * 凭据未过期
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return !this.enabled.equals(UserStatusEnum.OVERDUE.getValue());
    }

    @Override
    public boolean isEnabled() {
        return this.enabled.equals(UserStatusEnum.OFFLINE.getValue()) ||
                this.enabled.equals(UserStatusEnum.ONLINE.getValue());
    }

    @Override
    public void eraseCredentials() {
        this.password = null;
    }
}
